import mongoose, { Schema, Document } from 'mongoose';

/**
 * 工单状态
 */
export enum TicketStatus {
  OPEN = 'open',               // 待处理
  IN_PROGRESS = 'in_progress', // 处理中
  PENDING = 'pending',         // 挂起（等待外部条件）
  RESOLVED = 'resolved',       // 已解决
  CLOSED = 'closed',           // 已关闭
}

/**
 * 工单优先级
 */
export enum TicketPriority {
  CRITICAL = 'critical',  // 紧急
  HIGH = 'high',         // 高
  MEDIUM = 'medium',     // 中
  LOW = 'low',           // 低
}

/**
 * 工单类型
 */
export enum TicketType {
  INCIDENT = 'incident',     // 故障
  ALERT = 'alert',          // 告警
  MAINTENANCE = 'maintenance', // 维护
  REQUEST = 'request',      // 请求
}

/**
 * 工单评论
 */
export interface ITicketComment {
  userId: mongoose.Types.ObjectId;
  userName: string;
  content: string;
  isInternal: boolean;  // 是否是内部评论（不对外显示）
  createdAt: Date;
}

/**
 * 工单状态变更历史
 */
export interface ITicketStatusChange {
  from: TicketStatus;
  to: TicketStatus;
  userId: mongoose.Types.ObjectId;
  userName: string;
  reason?: string;
  changedAt: Date;
}

/**
 * 工单接口定义
 */
export interface ITicket extends Document {
  _id: mongoose.Types.ObjectId;

  // 基本信息
  ticketNumber: string;         // 工单编号（自动生成）
  title: string;                // 标题
  description: string;          // 描述
  type: TicketType;            // 类型
  priority: TicketPriority;    // 优先级
  status: TicketStatus;        // 状态

  // 关联信息
  alertId?: mongoose.Types.ObjectId;  // 关联的告警 ID
  relatedTickets?: mongoose.Types.ObjectId[]; // 相关工单

  // 人员信息
  createdBy: mongoose.Types.ObjectId;   // 创建人
  assignedTo?: mongoose.Types.ObjectId; // 负责人
  watchers: mongoose.Types.ObjectId[];  // 关注者

  // 处理信息
  comments: ITicketComment[];           // 评论列表
  statusHistory: ITicketStatusChange[]; // 状态变更历史

  // 解决方案
  resolution?: {
    solution: string;        // 解决方案
    resolvedBy: mongoose.Types.ObjectId;
    resolvedAt: Date;
    rootCause?: string;      // 根因
    preventiveMeasures?: string; // 预防措施
  };

  // SLA 管理
  sla?: {
    responseDeadline: Date;  // 响应截止时间
    resolutionDeadline: Date; // 解决截止时间
    isBreached: boolean;      // 是否违反 SLA
  };

  // 标签
  tags: string[];

  // 时间戳
  createdAt: Date;
  updatedAt: Date;
  closedAt?: Date;

  // 实例方法
  addComment(userId: mongoose.Types.ObjectId, userName: string, content: string, isInternal?: boolean): Promise<ITicket>;
  updateStatus(newStatus: TicketStatus, userId: mongoose.Types.ObjectId, userName: string, reason?: string): Promise<ITicket>;
  assign(userId: mongoose.Types.ObjectId, assignedBy: mongoose.Types.ObjectId, assignedByName: string): Promise<ITicket>;
}

/**
 * 工单数据模型
 */
const TicketSchema = new Schema<ITicket>(
  {
    ticketNumber: {
      type: String,
      unique: true,
      index: true,
      sparse: true, // 允许多个null值，直到pre-save hook生成
    },
    title: {
      type: String,
      required: true,
      trim: true,
      maxlength: 200,
    },
    description: {
      type: String,
      required: true,
      trim: true,
    },
    type: {
      type: String,
      enum: Object.values(TicketType),
      required: true,
      index: true,
    },
    priority: {
      type: String,
      enum: Object.values(TicketPriority),
      required: true,
      index: true,
    },
    status: {
      type: String,
      enum: Object.values(TicketStatus),
      default: TicketStatus.OPEN,
      index: true,
    },

    // 关联信息
    alertId: {
      type: Schema.Types.ObjectId,
      ref: 'Alert',
      default: null,
      index: true,
    },
    relatedTickets: {
      type: [Schema.Types.ObjectId],
      ref: 'Ticket',
      default: [],
    },

    // 人员信息
    createdBy: {
      type: Schema.Types.ObjectId,
      ref: 'User',
      required: true,
      index: true,
    },
    assignedTo: {
      type: Schema.Types.ObjectId,
      ref: 'User',
      default: null,
      index: true,
    },
    watchers: {
      type: [Schema.Types.ObjectId],
      ref: 'User',
      default: [],
    },

    // 评论
    comments: {
      type: [
        {
          userId: {
            type: Schema.Types.ObjectId,
            ref: 'User',
            required: true,
          },
          userName: {
            type: String,
            required: true,
          },
          content: {
            type: String,
            required: true,
          },
          isInternal: {
            type: Boolean,
            default: false,
          },
          createdAt: {
            type: Date,
            default: Date.now,
          },
        },
      ],
      default: [],
    },

    // 状态历史
    statusHistory: {
      type: [
        {
          from: {
            type: String,
            enum: Object.values(TicketStatus),
            required: true,
          },
          to: {
            type: String,
            enum: Object.values(TicketStatus),
            required: true,
          },
          userId: {
            type: Schema.Types.ObjectId,
            ref: 'User',
            required: true,
          },
          userName: {
            type: String,
            required: true,
          },
          reason: {
            type: String,
            default: null,
          },
          changedAt: {
            type: Date,
            default: Date.now,
          },
        },
      ],
      default: [],
    },

    // 解决方案
    resolution: {
      solution: {
        type: String,
        default: null,
      },
      resolvedBy: {
        type: Schema.Types.ObjectId,
        ref: 'User',
        default: null,
      },
      resolvedAt: {
        type: Date,
        default: null,
      },
      rootCause: {
        type: String,
        default: null,
      },
      preventiveMeasures: {
        type: String,
        default: null,
      },
    },

    // SLA
    sla: {
      responseDeadline: {
        type: Date,
        default: null,
      },
      resolutionDeadline: {
        type: Date,
        default: null,
      },
      isBreached: {
        type: Boolean,
        default: false,
      },
    },

    // 标签
    tags: {
      type: [String],
      default: [],
      index: true,
    },

    closedAt: {
      type: Date,
      default: null,
    },
  },
  {
    timestamps: true,
    versionKey: false,
  }
);

/**
 * 索引定义
 */
TicketSchema.index({ ticketNumber: 1 }, { unique: true });
TicketSchema.index({ status: 1, priority: 1 });
TicketSchema.index({ assignedTo: 1, status: 1 });
TicketSchema.index({ createdAt: -1 });
TicketSchema.index({ tags: 1 });

/**
 * 保存前钩子：生成工单编号
 */
TicketSchema.pre<ITicket>('save', async function (next) {
  if (this.isNew && !this.ticketNumber) {
    const count = await mongoose.model('Ticket').countDocuments();
    const date = new Date();
    const dateStr = date.toISOString().slice(0, 10).replace(/-/g, '');
    this.ticketNumber = `TK-${dateStr}-${String(count + 1).padStart(5, '0')}`;
  }
  next();
});

/**
 * 实例方法：添加评论
 */
TicketSchema.methods.addComment = function (
  userId: mongoose.Types.ObjectId,
  userName: string,
  content: string,
  isInternal: boolean = false
) {
  this.comments.push({
    userId,
    userName,
    content,
    isInternal,
    createdAt: new Date(),
  });
  return this.save();
};

/**
 * 实例方法：更新状态
 */
TicketSchema.methods.updateStatus = function (
  newStatus: TicketStatus,
  userId: mongoose.Types.ObjectId,
  userName: string,
  reason?: string
) {
  const oldStatus = this.status;
  this.status = newStatus;

  this.statusHistory.push({
    from: oldStatus,
    to: newStatus,
    userId,
    userName,
    reason,
    changedAt: new Date(),
  });

  if (newStatus === TicketStatus.CLOSED) {
    this.closedAt = new Date();
  }

  return this.save();
};

/**
 * Pre-save hook: 自动生成工单编号
 */
TicketSchema.pre('save', async function (next) {
  if (!this.ticketNumber) {
    // Generate ticket number: Format TKT-YYYYMMDD-XXXX
    const date = new Date();
    const dateStr = date.toISOString().slice(0, 10).replace(/-/g, '');

    // 查找当天最后一个工单号
    const lastTicket = await mongoose.model<ITicket>('Ticket')
      .findOne({
        ticketNumber: new RegExp(`^TKT-${dateStr}-`)
      })
      .sort({ ticketNumber: -1 });

    let sequence = 1;
    if (lastTicket) {
      const lastSequence = parseInt(lastTicket.ticketNumber.split('-')[2]);
      sequence = lastSequence + 1;
    }

    this.ticketNumber = `TKT-${dateStr}-${sequence.toString().padStart(4, '0')}`;
  }
  next();
});

/**
 * 实例方法：分配工单
 */
TicketSchema.methods.assign = function (
  assignedTo: mongoose.Types.ObjectId,
  userId: mongoose.Types.ObjectId,
  userName: string
) {
  this.assignedTo = assignedTo;
  return this.updateStatus(TicketStatus.IN_PROGRESS, userId, userName, '工单已分配');
};

/**
 * 静态方法：查询待处理工单
 */
TicketSchema.statics.findPending = function (assignedTo?: mongoose.Types.ObjectId) {
  const query: any = {
    status: { $in: [TicketStatus.OPEN, TicketStatus.IN_PROGRESS, TicketStatus.PENDING] },
  };

  if (assignedTo) {
    query.assignedTo = assignedTo;
  }

  return this.find(query).sort({ priority: -1, createdAt: -1 });
};

export default mongoose.model<ITicket>('Ticket', TicketSchema);
